/*
 * Created on Feb 25, 2005
 *
 */
package net.jxta.myjxta.plugins.tictactoe;

import net.jxta.document.*;
import net.jxta.endpoint.MessageElement;
import net.jxta.endpoint.TextDocumentMessageElement;
import net.jxta.logging.Logging;
import net.jxta.myjxta.View;
import net.jxta.myjxta.dialog.Dialog;
import net.jxta.myjxta.dialog.DialogManager;
import net.jxta.myjxta.dialog.DialogMessage;
import net.jxta.myjxta.dialog.util.RemoteCommandInvoker;
import net.jxta.myjxta.plugins.tictactoe.commands.TicTacToeCommand;
import net.jxta.myjxta.util.Group;
import net.jxta.myjxta.util.Peer;
import net.jxta.myjxta.util.Resources;
import net.jxta.myjxta.util.objectmodel.PeerNode;
import net.jxta.pipe.PipeService;
import net.jxta.protocol.PipeAdvertisement;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;

public class TicTacToeInviteAction extends AbstractAction {

    private static final int INTERVAL = 250;
    private static final int MAX = INTERVAL * 4 * 75;
    private static final Logger LOG = Logger.getLogger(TicTacToeInviteAction.class.getName());

    private View view = null;

    private static final ResourceBundle STRINGS = Resources.getStrings();

    public TicTacToeInviteAction(String name, View view) {
        super(name);

        this.view = view;

        if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) {
            LOG.fine("TicTavToeAction instantiated");
        }
    }

    public void actionPerformed(ActionEvent ae) {
        PeerNode pn = (PeerNode) this.view.getJxtaNode(PeerNode.class);
        final Peer p = pn != null ? pn.getPeer() : null;
        final Group g = pn != null ? pn.getParent().getGroup() : null;
        String status;

        if (p != null && g != null) {
            status = STRINGS.getString("status.command.initiate") +
                    ": " + p.getName();

            if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
                LOG.info(status);
            }

            new Thread(new Runnable() {
                public void run() {
                    process(g, p);
                }
            }, getClass().getName() + ":getConnection").start();
        } else {
            String peerName=p==null?"null":p.getName();
            status = STRINGS.getString("error.peer.invalid") + " " + peerName;

            if (Logging.SHOW_SEVERE && LOG.isLoggable(Level.SEVERE)) {
                LOG.severe(status);
            }
        }

        if (status != null) {
            this.view.setStatus(status);
        }
    }

    private void process(Group g, Peer p) {
        LOG.setLevel(Level.INFO);
        String status = "initiating tictactoe action";
        this.view.setStatus(status);

        if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
            LOG.info(status);
        }

        //get pipe adv from DialogManager - this is the tictactoePipe
        StructuredDocument d = getPipeAdv(g);
        //attach it as a message element
        TextDocumentMessageElement te = d != null ?
                new TextDocumentMessageElement(TicTacToeCommand.PIPE,
                        (StructuredTextDocument) d, null) :
                null;


        if (te != null) {


            if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
                LOG.info(status);
                LOG.info("instantiating tictactoeCommand");
            }

            //command fetecher will send out a command on the command pipe
            RemoteCommandInvoker cf = new RemoteCommandInvoker(g, p.getPipeAdvertisement(),
                    new TicTacToeCommand(), this.view.getControl());

            Map<String, MessageElement> m = new HashMap<String, MessageElement>();
            // add the our pipe element
            m.put(TicTacToeCommand.PIPE, te);

            if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
                LOG.info("dispatch tictactoecommand");
            }

            cf.invoke(MAX, m);
            //get respsonse
            DialogMessage r = cf.getResponse();

            if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
                LOG.info("tictactoeInvitationCommand response: " + r);
            }
            //this is why its important to have a consistent PIPE element in TestCommand
            MessageElement pae = r != null ?
                    r.getMessageElement(TicTacToeCommand.PIPE) :
                    null;

            if (pae != null) {
                status = "tictactoe pipe import" +
                        ": " + p.getName();

                this.view.setStatus(status);

                if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
                    LOG.info(status);
                    LOG.info("adding dialog");
                }


                PipeAdvertisement pipeAdv = getPipeAdv(pae);
                if (pipeAdv != null) {
                    TicTacToeDialog dialog = (TicTacToeDialog) DialogManager.getDialog(TicTacToeDialog.class,
                            g, pipeAdv, this.view.getControl());
                    dialog.setLocallyInitiated(true);
                    this.view.getControl().addDialog(
                            dialog);
                } else {
                    //this can happen! maybe if the user connects to his own peer?
                }
            } else {
                status = "request tictactoe pipe" +
                        ": " + p.getName();

                this.view.setStatus(status);

                if (Logging.SHOW_SEVERE && LOG.isLoggable(Level.SEVERE)) {
                    LOG.severe(status);
                }
            }
        } else {
            if (Logging.SHOW_SEVERE && LOG.isLoggable(Level.SEVERE)) {
                LOG.severe("invalid response");
            }
        }


        LOG.setLevel(Level.SEVERE);
    }

    private PipeAdvertisement getPipeAdv(MessageElement me) {
        if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
            LOG.info("get pipeAdv");
        }

        StructuredDocument sd = null;

        try {
            sd = StructuredDocumentFactory.newStructuredDocument(MimeMediaType.XMLUTF8,
                    me.getStream());
        } catch (IOException e) {
            LOG.log(Level.SEVERE, "can\'t document", e);
        }

//        if (me instanceof ByteArrayMessageElement) {
//            if (LOG.isEnabledFor (Level.INFO)) {
//                LOG.info ("me instanceof ByteMessageElement");
//            }
//
//            try {
//                sd = StructuredDocumentFactory.newStructuredDocument (MimeMediaType.XMLUTF8,
//                        ((ByteArrayMessageElement)me).getStream ());
//            } catch (IOException ioe) {
//                if (LOG.isEnabledFor (Level.SEVERE)) {
//                    LOG.error ("can't document", ioe);
//                }
//            }
//        } else {
//            if (LOG.isEnabledFor (Level.INFO)) {
//                LOG.info ("me not instanceof ByteMessageElement");
//            }
//        }

        PipeAdvertisement pa = null;

        if (sd != null) {
            try {
                XMLDocument xml = (XMLDocument) StructuredDocumentFactory.newStructuredDocument( MimeMediaType.XMLUTF8, sd.getStream() );
                pa = (PipeAdvertisement) AdvertisementFactory.
                        newAdvertisement(xml);
            } catch (IOException ioe) {
                if (Logging.SHOW_SEVERE && LOG.isLoggable(Level.SEVERE)) {
                    LOG.log(Level.SEVERE, "can\'t get pipe advertisement", ioe);
                }
            }
        }

        return pa;
    }

    private StructuredDocument getPipeAdv(Group g) {
        if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
            LOG.info("getPipeAdvl");
        }
        System.out.println("TTT Dilaog in invite action");
        String pn = Dialog.getDialogNamer(TicTacToeDialog.class).
                getDialogName(g.getPeerGroup().getPeerName());
        PipeAdvertisement pa = DialogManager.getInstance(g, pn,
                PipeService.UnicastType).getPipeAdv(g.getPeerGroup());

        return (StructuredDocument) pa.getDocument(MimeMediaType.XMLUTF8);
    }


}
